import ModbusRTU from "modbus-serial"
import { TcpPortOptions } from "modbus-serial/ModbusRTU"
import YAML from 'yamljs'
const Settings = YAML.load('settings.yaml')
const LORA_MODBUSTCP = Settings.LORA_MODBUSTCP
const client = new ModbusRTU()
const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))
let WriteTimerCoilTimeOut = {};
let CoilsStatus = {};
interface cmdType {
    type: string,
    id: number,
    addr: number,
    status: number
}
var cmdList: cmdType[] = [
    // { "type": "readCoils", "id": 3, "addr": 0, "status": 16 },
    // { "type": "writeCoil", "id": 3, "addr": 0, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 1, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 2, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 3, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 4, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 5, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 6, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 7, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 8, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 9, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 10, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 11, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 12, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 13, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 14, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 15, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 16, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 17, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 18, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 19, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 20, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 21, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 22, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 23, "status": 0 },
    // { "type": "writeCoil", "id": 3, "addr": 0, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 1, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 2, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 3, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 4, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 5, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 6, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 7, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 8, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 9, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 10, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 11, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 12, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 13, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 14, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 15, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 16, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 17, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 18, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 19, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 20, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 21, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 22, "status": 1 },
    // { "type": "writeCoil", "id": 3, "addr": 23, "status": 1 }
]
var option: TcpPortOptions = {
    port: 502
}
function config() {
    // open connection to a serial port
    if (LORA_MODBUSTCP.type == 0) {
        console.log(`以太网连接控制`)
        client.connectTCP(LORA_MODBUSTCP.host, option).then(() => {

        });
    } else if (LORA_MODBUSTCP.type == 1) {
        console.log(`串口连接控制`)
        client.connectRTUBuffered(LORA_MODBUSTCP.com, { baudRate: LORA_MODBUSTCP.baudRate });
    }

    // set timeout, if slave did not reply back
    client.setTimeout(500)
    // list of meter's id

    // start get value
    // setTimeout(() => {
    //     setCoilsValue(cmdList)
    // }, 1000)

}


async function cycleCtrl() {
    try {
        let meter = cmdList.shift()
        if (meter) {
            // console.log(meter)
            await client.setID(meter.id)
            let val1 = await client.writeCoil(meter.addr, meter.status == 0 ? false : true)
            // return the value
            if (val1.address != undefined) {
                console.log(`id:${meter.id},ch:${meter.addr}${meter.status == 0 ? "关闭" : "开启"}成功(0)`)
                CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`] = true;
                console.log(`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`, CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`], Date.now())
                cycleCtrl()
            } else {
                await sleep(30)
                val1 = await client.writeCoil(meter.addr, meter.status == 0 ? false : true)
                if (val1.address != undefined) {
                    console.log(`id:${meter.id},ch:${meter.addr}${meter.status == 0 ? "关闭" : "开启"}成功(1)`)
                    CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`] = true;
                    console.log(`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`, CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`])
                    await sleep(30)
                    cycleCtrl()
                } else {
                    await sleep(30)
                    val1 = await client.writeCoil(meter.addr, meter.status == 0 ? false : true)
                    if (val1.address != undefined) {
                        console.log(`id:${meter.id},ch:${meter.addr}${meter.status == 0 ? "关闭" : "开启"}成功(1)`)
                        CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`] = true;
                        console.log(`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`, CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`])
                        await sleep(30)
                        cycleCtrl()
                    } else {
                        console.log(`失败重发=======》》》》》失败！！！！！`)
                        CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`] = false;
                        console.log(`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`, CoilsStatus[`${LORA_MODBUSTCP.host}_${meter.id}_${meter.addr}`])
                        await sleep(30)
                        cycleCtrl()
                    }
                }
            }
        } else {
            await sleep(30)
            cycleCtrl()
        }
    } catch (error) {
        await sleep(30)
        cycleCtrl()
    }

}
config()
cycleCtrl();



function WriteTimerCoils(host: string, stationNumber: number, adressArr: Array<number>, openTimeSecArr: Array<number>, retryInterval: number, retryNumber: number, isBackOff: boolean, next: Function) {
    try {
        console.log(host, stationNumber, adressArr, openTimeSecArr)
        let ackTime: Array<number> = [];
        for (let i = 0; i < openTimeSecArr.length; i++) {
            const element = openTimeSecArr[i] - 2;
            ackTime[i] = element;
        }
        let data = {
            openTimeSecArr: ackTime
        }
        for (let i = 0; i < adressArr.length; i++) {

            let cmd = {
                "type": "writeCoil",
                "id": stationNumber,
                "addr": adressArr[i],
                "status": 0
            }
            let cmd1 = {
                "type": "writeCoil",
                "id": stationNumber,
                "addr": adressArr[i],
                "status": 0
            }
            console.log(`${host}_${stationNumber}_${adressArr[i]}`, '======================')
            if (WriteTimerCoilTimeOut[`${host}_${stationNumber}_${adressArr[i]}`]) {
                clearTimeout(WriteTimerCoilTimeOut[`${host}_${stationNumber}_${adressArr[i]}`]);
                WriteTimerCoilTimeOut[`${host}_${stationNumber}_${adressArr[i]}`] = null;
            }
            if (openTimeSecArr[i] == 0) {
                cmd.status = 0;
                cmdList.push(cmd)
                CoilsStatus[`${host}_${stationNumber}_${adressArr[i]}`] = false;
            } else {
                cmd.status = 1;
                CoilsStatus[`${host}_${stationNumber}_${adressArr[i]}`] = false;
                cmdList.push(cmd)
                WriteTimerCoilTimeOut[`${host}_${stationNumber}_${adressArr[i]}`] = setTimeout(() => {
                    WriteTimerCoilTimeOut[`${host}_${stationNumber}_${adressArr[i]}`] = null;
                    cmdList.push(cmd1)
                }, openTimeSecArr[i] * 1000)
            }
        }
        let timeOutCount = adressArr.length;
        if (timeOutCount > 4) {
            timeOutCount = 4;
        }
        setTimeout(() => {
            if (CoilsStatus[`${host}_${stationNumber}_${adressArr[0]}`] == true && CoilsStatus[`${host}_${stationNumber}_${adressArr[adressArr.length - 1]}`] == true) {
                console.log(`完全控制成功`)
                next(null, data)
            } else {
                console.log(`\x1b[30;33m控制失败`, `${host}_${stationNumber}_${adressArr[0]}`, CoilsStatus[`${host}_${stationNumber}_${adressArr[0]}`], `${host}_${stationNumber}_${adressArr[adressArr.length - 1]}`, CoilsStatus[`${host}_${stationNumber}_${adressArr[adressArr.length - 1]}`] == true, "\x1b[30;37m")
                next(`\x1b[30;33m控制失败`, [])
            }
        }, timeOutCount * 500 + 2000)
    } catch (e) {
        console.log(e)
    } finally {

    }

}

export {
    config,
    WriteTimerCoils
}